using ImageCSharp.Core.Interfaces;
using ImageCSharp.Core.Models;
using ImageCSharp.Core.Events;
using CommunityToolkit.Mvvm.Messaging;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System;
using SixLabors.ImageSharp.Drawing; // Pen/SolidBrush 所在命名空间
using SixLabors.ImageSharp.Drawing.Processing; // DrawLines 扩展方法所在命名空间

namespace ImageCSharp.Core.Services
{
    /// <summary>
    /// 工具服务实现
    /// </summary>
    public class ToolService : IToolService
    {
        private Tool? _selectedTool;
        private readonly List<Tool> _availableTools = new();
        private readonly IMessenger _messenger;
        private SixLabors.ImageSharp.Point _selectionStartPoint; 
        private SixLabors.ImageSharp.Point _selectionEndPoint;
        private bool _isSelecting;
        private bool _isDrawing;
        private SixLabors.ImageSharp.Point _lastDrawPoint;

        public ToolService(IMessenger messenger)
        {
            _messenger = messenger;
            InitializeTools();
        }

        public void SelectTool(Tool tool)
        {
            if (_selectedTool != null)
                _selectedTool.IsActive = false;

            _selectedTool = tool;
            
            if (_selectedTool != null)
                _selectedTool.IsActive = true;

            // 发送工具变更事件
            _messenger.Send(new ToolChangedEvent(tool));
        }

        private void InitializeTools()
        {
            // 初始化所有可用工具
            _availableTools.AddRange(new Tool[]
            {
                new SelectionTool 
                { 
                    Name = "选择工具", 
                    IconPath = "Selection",
                    Description = "用于选择图像区域",
                    Type = ToolType.Selection
                },
                new DrawingTool 
                { 
                    Name = "画笔工具", 
                    IconPath = "Brush",
                    Description = "用于绘制图像",
                    Type = ToolType.Drawing,
                    BrushSize = 5,
                    Color = SixLabors.ImageSharp.Color.Black
                },
                new MeasurementTool 
                { 
                    Name = "测量工具", 
                    IconPath = "Ruler",
                    Description = "用于测量距离和角度",
                    Type = ToolType.Measurement
                },
                new EraserTool 
                { 
                    Name = "橡皮擦工具", 
                    IconPath = "Eraser",
                    Description = "用于擦除图像内容",
                    Type = ToolType.Eraser,
                    BrushSize = 10
                },
                new MagicWandTool 
                { 
                    Name = "魔术棒工具", 
                    IconPath = "MagicWand",
                    Description = "基于颜色相似性选择区域",
                    Type = ToolType.MagicWand,
                    Tolerance = 0.1f
                }
            });
        }

        public Tool? GetSelectedTool()
        {
            return _selectedTool;
        }

        public List<Tool> GetAvailableTools()
        {
            return _availableTools;
        }

        public void ExecuteToolAction(ImageDocument document, ToolAction action)
        {
            if (_selectedTool == null || document == null)
                return;

            // 根据工具类型执行相应的操作
            switch (_selectedTool.Type)
            {
                case ToolType.Selection:
                    ExecuteSelectionTool(document, action);
                    break;

                case ToolType.Drawing:
                    ExecuteDrawingTool(document, action);
                    break;

                case ToolType.Measurement:
                    ExecuteMeasurementTool(document, action);
                    break;
            }

            // 记录工具操作到历史记录
            if (action.Type == ToolActionType.MouseUp)
            {
                RecordToolAction(_selectedTool, action);
            }
        }

        private void RecordToolAction(Tool tool, ToolAction action)
        {
            string actionDescription = $"使用 {tool.Name}";
            
            if (tool is SelectionTool selectionTool)
            {
                actionDescription += $" ({selectionTool.Mode})";
            }
            else if (tool is DrawingTool drawingTool)
            {
                actionDescription += $" (大小: {drawingTool.BrushSize}, 颜色: {drawingTool.Color})";
            }
            
            // 这里应该通过事件通知历史记录服务
            // 实际项目中应该使用依赖注入或事件总线
        }

        private void ExecuteSelectionTool(ImageDocument document, ToolAction action)
        {
            if (_selectedTool is not SelectionTool selectionTool)
                return;

            switch (action.Type)
            {
                case ToolActionType.MouseDown:
                    _isSelecting = true;
                    _selectionStartPoint = action.StartPoint;
                    _selectionEndPoint = action.StartPoint;
                    break;
                case ToolActionType.MouseMove:
                    if (_isSelecting)
                    {
                        _selectionEndPoint = action.CurrentPoint;
                        // 发送选择区域变更事件
                        var selectionRect = new SixLabors.ImageSharp.RectangleF(
                            Math.Min(_selectionStartPoint.X, _selectionEndPoint.X),
                            Math.Min(_selectionStartPoint.Y, _selectionEndPoint.Y),
                            Math.Abs(_selectionEndPoint.X - _selectionStartPoint.X),
                            Math.Abs(_selectionEndPoint.Y - _selectionStartPoint.Y));
                        _messenger.Send(new SelectionChangedEvent(selectionRect));
                    }
                    break;

                case ToolActionType.MouseUp:
                    if (_isSelecting)
                    {
                        _isSelecting = false;
                        _selectionEndPoint = action.EndPoint;
                        
                        // 根据选择模式创建不同的选择区域
                        SixLabors.ImageSharp.RectangleF selectionArea = selectionTool.Mode switch
                        {
                            SelectionMode.Rectangle => new SixLabors.ImageSharp.RectangleF(
                                Math.Min(_selectionStartPoint.X, _selectionEndPoint.X),
                                Math.Min(_selectionStartPoint.Y, _selectionEndPoint.Y),
                                Math.Abs(_selectionEndPoint.X - _selectionStartPoint.X),
                                Math.Abs(_selectionEndPoint.Y - _selectionStartPoint.Y)),
                            SelectionMode.Ellipse => CreateEllipticalSelection(_selectionStartPoint, _selectionEndPoint),
                            _ => new SixLabors.ImageSharp.RectangleF(
                                Math.Min(_selectionStartPoint.X, _selectionEndPoint.X),
                                Math.Min(_selectionStartPoint.Y, _selectionEndPoint.Y),
                                Math.Abs(_selectionEndPoint.X - _selectionStartPoint.X),
                                Math.Abs(_selectionEndPoint.Y - _selectionStartPoint.Y))
                        };

                        document.SelectionArea = selectionArea;
                        _messenger.Send(new SelectionChangedEvent(selectionArea));
                    }
                    break;
            }
        }

        private SixLabors.ImageSharp.RectangleF CreateEllipticalSelection(SixLabors.ImageSharp.Point start, SixLabors.ImageSharp.Point end)
        {
            return new SixLabors.ImageSharp.RectangleF(
                Math.Min(start.X, end.X),
                Math.Min(start.Y, end.Y),
                Math.Abs(end.X - start.X),
                Math.Abs(end.Y - start.Y));
        }

        private void ExecuteDrawingTool(ImageDocument document, ToolAction action)
        {
            if (_selectedTool is not DrawingTool drawingTool)
                return;

            switch (action.Type)
            {
                case ToolActionType.MouseDown:
                    _isDrawing = true;
                    _lastDrawPoint = action.StartPoint;
                    break;

                case ToolActionType.MouseMove:
                    if (_isDrawing)
                    {
                        // 在图像上绘制线条
                        DrawLine(document.Image, _lastDrawPoint, action.CurrentPoint, drawingTool);
                        _lastDrawPoint = action.CurrentPoint;
                    }
                    break;

                case ToolActionType.MouseUp:
                    if (_isDrawing)
                    {
                        _isDrawing = false;
                        // 完成绘制
                        DrawLine(document.Image, _lastDrawPoint, action.EndPoint, drawingTool);
                    }
                    break;
            }
        }

        //private void DrawLine(Image<Rgba32> image, SixLabors.ImageSharp.Point start, SixLabors.ImageSharp.Point end, DrawingTool tool)
        //{
        //    // 使用ImageSharp绘制线条
        //    image.Mutate(ctx =>
        //    {
        //        ctx.DrawLines(
        //            new SixLabors.ImageSharp.Drawing.Pen(
        //                new SixLabors.ImageSharp.Drawing.SolidBrush(
        //                    new Rgba32(tool.Color.R, tool.Color.G, tool.Color.B, (byte)(tool.Opacity * 255))),
        //                tool.BrushSize),
        //            new SixLabors.ImageSharp.PointF(start.X, start.Y),
        //            new SixLabors.ImageSharp.PointF(end.X, end.Y)
        //        );
        //    });
        //}


        private void DrawLine(Image<Rgba32> image, PointF start, PointF end, DrawingTool tool)
        {
            // 简单的 Bresenham 线条算法实现
            DrawLineBresenham(image, start, end, tool);
        }

        private void DrawLineBresenham(Image<Rgba32> image, PointF start, PointF end, DrawingTool tool)
        {
            int x0 = (int)start.X;
            int y0 = (int)start.Y;
            int x1 = (int)end.X;
            int y1 = (int)end.Y;

            int dx = Math.Abs(x1 - x0);
            int dy = Math.Abs(y1 - y0);
            int sx = (x0 < x1) ? 1 : -1;
            int sy = (y0 < y1) ? 1 : -1;
            int err = dx - dy;

            while (true)
            {
                // 绘制当前点
                DrawPoint(image, x0, y0, tool);

                if (x0 == x1 && y0 == y1)
                    break;

                int e2 = 2 * err;
                if (e2 > -dy)
                {
                    err -= dy;
                    x0 += sx;
                }
                if (e2 < dx)
                {
                    err += dx;
                    y0 += sy;
                }
            }
        }

        private void DrawPoint(Image<Rgba32> image, int x, int y, DrawingTool tool)
        {
            // 确保坐标在图像范围内
            if (x >= 0 && x < image.Width && y >= 0 && y < image.Height)
            {
                // 绘制一个点（简单实现，可以扩展为绘制圆形或其他形状）
                for (int i = -tool.BrushSize / 2; i <= tool.BrushSize / 2; i++)
                {
                    for (int j = -tool.BrushSize / 2; j <= tool.BrushSize / 2; j++)
                    {
                        int px = x + i;
                        int py = y + j;

                        if (px >= 0 && px < image.Width && py >= 0 && py < image.Height)
                        {
                            // 简单的距离检查，创建圆形笔刷效果
                            double distance = Math.Sqrt(i * i + j * j);
                            if (distance <= tool.BrushSize / 2.0)
                            {
                                image[px, py] = tool.Color;
                            }
                        }
                    }
                }
            }
        }


        private void ExecuteMeasurementTool(ImageDocument document, ToolAction action)
        {
            if (_selectedTool is not MeasurementTool measurementTool)
                return;

            switch (action.Type)
            {
                case ToolActionType.MouseDown:
                    _selectionStartPoint = action.StartPoint;
                    break;

                case ToolActionType.MouseUp:
                    _selectionEndPoint = action.EndPoint;
                    
                    var result = new MeasurementResult
                    {
                        StartPoint = _selectionStartPoint,
                        EndPoint = _selectionEndPoint,
                        Distance = CalculateDistance(_selectionStartPoint, _selectionEndPoint),
                        Angle = CalculateAngle(_selectionStartPoint, _selectionEndPoint)
                    };

                    // 发送测量结果事件
                    _messenger.Send(new MeasurementCompletedEvent(result));
                    
                    // 更新状态栏消息
                    var message = measurementTool.Mode switch
                    {
                        MeasurementMode.Distance => $"距离: {result.Distance:F2} {result.Unit}",
                        MeasurementMode.Angle => $"角度: {result.Angle:F2}°",
                        _ => $"测量完成: {result.Distance:F2} {result.Unit}"
                    };
                    _messenger.Send(new StatusMessageEvent(message));
                    break;
            }
        }

        private double CalculateDistance(SixLabors.ImageSharp.Point start, SixLabors.ImageSharp.Point end)
        {
            return Math.Sqrt(
                Math.Pow(end.X - start.X, 2) +
                Math.Pow(end.Y - start.Y, 2));
        }

        private double CalculateAngle(SixLabors.ImageSharp.Point start, SixLabors.ImageSharp.Point end)
        {
            return Math.Atan2(end.Y - start.Y, end.X - start.X) * 180 / Math.PI;
        }
    }
}